import { EventEmitter } from "events";
import { dirname, resolve } from "path";
import { findAllFiles } from "../FileUtil";

var Client = require('ftp');
export class FtpClient extends EventEmitter {
    private _ftp: any;
    private _isReady: boolean = false;
    private _opts: IFtpOptions;
    constructor(option: IFtpOptions) {
        super();
        this._opts = option;
        this._ftp = new Client();
        this._ftp.on("ready", () => {
            this._isReady = true;
            this.emit("ready");
        });
        this._ftp.on("close", () => {
            this._isReady = false;
            this.emit("close");
        })
        this._ftp.on("error", () => {
            this._isReady = false;
            this._ftp.end();
            this.emit("error");
        })
    }

    get connected(){
        return this._isReady;
    }

    async connect() {
        return new Promise((resolve) => {
            this.once("ready", () => {
                resolve(null);
            });
            this._ftp.connect(this._opts);
        })
    }

    async list(path: string, zcomp?: boolean) {
        return new Promise((resolve, reject) => {
            this._ftp.list(path, zcomp, (err, list) => {
                if (err) reject(err);
                resolve(list);
            })
        })
    }

    async put(file: string, path: string, zcomp?: boolean) {
        return new Promise((resolve, reject) => {
            this._ftp.put(file, path, zcomp, function (err) {
                if (err) {
                    reject(err);
                }
                resolve(null);
            });
        });
    }

    async putDir(path: string, toPath: string, zcomp?: boolean) {
        let files = findAllFiles(path);
        let successCount = 0;
        let total = files.length;
        let pathCache = "";
        for (let i = 0; i < files.length; i++) {
            try {
                let file: string = files[i];
                let toFile = toPath + file.replace(path, "").replace(/\\/g, "\/");
                let toDir = dirname(toFile);
                if (pathCache.indexOf(toDir) == -1) {
                    await this.mkdir(toDir,true);
                    pathCache += "," + toDir;
                }
                await this.put(file, toFile, zcomp);
                successCount++;
            } catch (e) {
                console.log("失败了",e)
            }
        }
        return { count: successCount, total: total };
    }

    async mkdir(path: string, recursive: boolean = false) {
        return new Promise((resolve, reject) => {
            this._ftp.mkdir(path, recursive, (err, text, code) => {
                if (err) {
                    reject(err);
                }
                resolve(text);
            })
        })
    }

    async pwd() {
        return new Promise((resolve, reject) => {
            this._ftp.pwd((err, pwd) => {
                if (err) {
                    reject(err);
                }
                resolve(pwd);
            })
        })
    }

    close() {
        this._ftp.end();
    }
}


export interface IFtpOptions {
    host?: string;
    port?: number;
    user?: string;
    password?: string;
    secure?: boolean;
    connTimeout?: number;
    pasvTimeout?: number;
    aliveTimeout?: number;
    debug?: Function;
}